import os
import io
from docx import Document
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
from application.settings import BASE_DIR
from django.http import FileResponse
from pathlib import Path
from docx.shared import Pt


def set_table_borders(table, color="000000", size=9, style="single"):
    """设置表格的边框样式"""
    tblPr = table._tbl.tblPr
    tblBorders = OxmlElement("w:tblBorders")
    for edge in ["top", "bottom", "left", "right", "insideH", "insideV"]:
        border = OxmlElement(f"w:{edge}")
        border.set(qn("w:color"), color)
        border.set(qn("w:sz"), str(size))
        border.set(qn("w:val"), style)
        tblBorders.append(border)
    if tblPr is None:
        tblPr = OxmlElement("w:tblPr")
        table._tbl.tblPr = tblPr
    tblPr.insert(0, tblBorders)


def handle_steps(steps, type="step"):
    """从步骤数据生成文本内容"""
    return "\n".join(f"{step.get('id')}.{step.get(type, '')}" for step in steps)


def create_test_case_table(doc, testcase, params):
    """根据给定的测试用例数据创建测试用例表格"""
    row_titles = []
    row_details = []

    if params.get("hasCaseName") == "0":
        title_case_name = (
            params.get("titleCaseName") if params.get("titleCaseName") else "用例名称"
        )
        row_titles.append(title_case_name)
        row_details.append(testcase.get("name", ""))

    if params.get("hasCaseModule") == "0":
        title_case_module = (
            params.get("titleCaseModule")
            if params.get("titleCaseModule")
            else "模块名称"
        )
        row_titles.append(title_case_module)
        row_details.append(testcase.get("module", ""))

    if params.get("hasCaseDesc") == "0":
        title_case_desc = (
            params.get("titleCaseDesc") if params.get("titleCaseDesc") else "测试说明"
        )
        row_titles.append(title_case_desc)
        row_details.append(testcase.get("description", ""))

    if params.get("hasCasePrec") == "0":
        title_case_prec = (
            params.get("titleCasePrec") if params.get("titleCasePrec") else "预置条件"
        )
        row_titles.append(title_case_prec)
        row_details.append(testcase.get("precondition", ""))

    if params.get("hasCaseSteps") == "0":
        title_case_steps = (
            params.get("titleCaseSteps") if params.get("titleCaseSteps") else "测试步骤"
        )
        row_titles.append(title_case_steps)
        row_details.append(handle_steps(testcase.get("steps", []), "step"))

    if params.get("hasCaseExps") == "0":
        title_case_exps = (
            params.get("titleCaseExps") if params.get("titleCaseExps") else "预期结果"
        )
        row_titles.append(title_case_exps)
        row_details.append(handle_steps(testcase.get("steps", []), "exp"))

    if params.get("hasCaseActuals") == "0":
        title_case_actuals = (
            params.get("titleCaseActuals")
            if params.get("titleCaseActuals")
            else "实际结果"
        )
        row_titles.append(title_case_actuals)
        row_details.append(handle_steps(testcase.get("steps", []), "result"))

    if params.get("hasCaseConclusion") == "0":
        title_case_conclusion = (
            params.get("titleCaseConclusion")
            if params.get("titleCaseConclusion")
            else "测试结论"
        )
        row_titles.append(title_case_conclusion)
        row_details.append("通过")

    table = doc.add_table(rows=len(row_titles), cols=4)

    for i, title in enumerate(row_titles):
        table.cell(i, 0).text = title
        table.cell(i, 1).merge(table.cell(i, 3))
        table.cell(i, 0).paragraphs[0].runs[0].bold = True
        table.cell(i, 0).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER

    for i, detail in enumerate(row_details):
        table.cell(i, 1).text = detail if detail else ""
        # 获取单元格的段落并设置对齐方式为左对齐
        for paragraph in table.cell(i, 1).paragraphs:
            paragraph.alignment = WD_ALIGN_PARAGRAPH.LEFT

    set_table_borders(table)

    return table


def generate_outline(title="测试大纲", dataset={}, params={}):
    """基于给定数据集生成文档大纲"""
    doc_path = BASE_DIR.joinpath(Path(params.get("template")).relative_to("/"))
    doc = Document(doc_path)

    for paragraph in doc.paragraphs:
        if "{{product_name}}" in paragraph.text:
            paragraph.text = paragraph.text.replace(
                "{{product_name}}", dataset.get("product_name")
            )

        if "{{product_number}}" in paragraph.text:
            paragraph.text = paragraph.text.replace(
                "{{product_number}}", dataset.get("product_number")
            )

        if "{{product_version}}" in paragraph.text:
            paragraph.text = paragraph.text.replace(
                "{{product_version}}", dataset.get("product_version")
            )

        if "{{product_description}}" in paragraph.text:
            paragraph.text = paragraph.text.replace(
                "{{product_description}}", dataset.get("product_description")
            )

        if "{{product_requirements}}" in paragraph.text:
            # 获取段落的父对象（通常是一个cell或者doc本身）
            parent_element = paragraph._element.getparent()
            # 找到段落在其父对象中的索引
            index_of_paragraph = parent_element.index(paragraph._element)
            for classify in dataset.get("product_requirements_testcases"):
                heading_1 = doc.add_heading(
                    f"{classify.get("name", "XX")}测试", level=2
                )
                parent_element.insert(index_of_paragraph, heading_1._element)
                index_of_paragraph += 1
                for requirement in classify.get("children", []):
                    heading_2 = doc.add_heading(
                        f"{requirement.get("name", "XX")}", level=3
                    )
                    parent_element.insert(index_of_paragraph, heading_2._element)
                    index_of_paragraph += 1

            # 清除占位符文本
            parent_element.remove(paragraph._element)

        if "{{product_requirements_testcases}}" in paragraph.text:
            # 获取段落的父对象（通常是一个cell或者doc本身）
            parent_element = paragraph._element.getparent()
            # 找到段落在其父对象中的索引
            index_of_paragraph = parent_element.index(paragraph._element)

            for classify in dataset.get("product_requirements_testcases"):
                heading_1 = doc.add_heading(
                    f"{classify.get("name", "XX")}测试", level=2
                )
                parent_element.insert(index_of_paragraph, heading_1._element)
                index_of_paragraph += 1
                for requirement in classify.get("children", []):
                    heading_2 = doc.add_heading(
                        f"{requirement.get("name", "XX")}", level=3
                    )
                    parent_element.insert(index_of_paragraph, heading_2._element)
                    index_of_paragraph += 1
                    for testcase in requirement.get("children", []):
                        if params.get("hasCaseHeading") == "0":
                            heading_3 = doc.add_heading(
                                testcase.get("name", "XX"), level=4
                            )
                            parent_element.insert(
                                index_of_paragraph, heading_3._element
                            )
                            index_of_paragraph += 1

                        # 添加 “测试方法”
                        if params.get("hasTestMethod") == "0":
                            test_method_paragraph = doc.add_paragraph(style="Normal")
                            run_bold = test_method_paragraph.add_run("测试方法：")
                            run_bold.bold = True
                            test_method_paragraph.add_run("□目测 □运行 □其他")

                            parent_element.insert(
                                index_of_paragraph, test_method_paragraph._element
                            )
                            index_of_paragraph += 1

                        table = create_test_case_table(doc, testcase, params)
                        parent_element.insert(index_of_paragraph, table._element)
                        index_of_paragraph += 1

            # 清除占位符文本
            parent_element.remove(paragraph._element)

    file_stream = io.BytesIO()
    doc.save(file_stream)
    file_stream.seek(0)

    response = FileResponse(file_stream, as_attachment=True, filename=f"{title}.docx")
    return response
